home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * MAKEXION.C
- *
- * (Simon Hern, 1994)
- *
- * Create compleXion data file for Bouncing Planets demo
- *
- * The Xion is generated randomly and written to the file XION.DAT
- * It's destined to become the surface of a planet (mercator map)
- * Uses sort-of-ish fractal generation on a spherical surface
- * The result is a RHO by 2*RHO bitmap in up to 256 colours
- *
- * For speed, uses an assembler language function from XIONCODE.ASM
- *
- */
-
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include <math.h>
-
- /* XLib v06 */
- #include <xfileio.h>
-
- /* Local definitions (notably RHO: the surface resolution) */
- #include "planet.h"
-
-
-
- /* Routine to displace an area of landscape (in XIONCODE.ASM) */
- extern void fracture(int rf_num, int blast, int x_start);
-
-
- /* Save 'far' arrays of data */
- int far_save(char * fname, char far * data, unsigned len);
-
-
-
- /* Surface generation parameters: */
- /* Strength of first break, and exponential decay of strength */
- #define FULL_BLAST 20.0
- #define POWER 3.0
-
- /* Final xion data scaled so altitudes lie between two extreme values */
- /* (This in effect defines the palette colours used for the final planet) */
- #define DEEPEST 1
- #define HIGHEST 80
-
- /* File to write data to */
- #define XION_FILE "XION.DAT"
-
-
-
- /* Precalculated values determining where landscape cracks */
- /* (This is used by the external 'fracture' function) */
- char riff[RHO/2][RHO/2];
-
- /* The (full size) skin array in which the surface is generated */
- /* (This array is a bit of a pain - it's exactly 64k long, and since it's */
- /* global it bloats the size of the compiled code. But the data needs an */
- /* entire memory segment to itself and dynamic memory allocation isn't */
- /* particularly sympathetic to that. I've given up fighting it.) */
- int huge skin[RHO][2*RHO];
-
-
-
- void main() {
-
- int strike; /* Number of fractures to make */
- int displac = 0; /* Move everything upwards; rebalance later */
-
- int blast; /* Depth of next fracture */
- int rf_num; /* Riff to use on this fracture */
- int r1; /* Preliminary random choice of riff */
- int half; /* Random choice of which half of surface to hit */
- int dirn; /* Random choice of whether to blast up or down */
- int x_start; /* Position around equator to start at */
- float r2, dis; /* Weight riff probabilities */
-
- float w, sig, gam; /* Partial calculations during riff formation */
-
- int x, y; /* Every program needs some x and y coordinates */
- int max, min; /* Maximum and minimum heights */
- int hgt; /* A height (for temporary purposes) */
-
- /* Final resting place of the xion data (after rescaling) */
- /* (Byte-size values rather than word-size values) */
- unsigned char xion[RHO][2*RHO];
-
-
-
- randomize();
-
-
- /* Generate the riff data (mathematical gibberish) */
- printf("Composing riffs\n");
- for ( y = 0 ; y < RHO/2 ; y++ ) {
- for ( x = 0 ; x < RHO/2 ; x++ ) {
- w = ( y + 0.5 ) * PI / RHO;
- sig = ( x + 0.5 ) * PI / RHO;
- gam = atan( tan(w) * cos(sig) );
- riff[y][x] = RHO/2 - (char)floor( gam * RHO/PI + 0.5 );
- }
- }
-
-
-
- /* Generate the surface */
- printf("Making %.0f fractures\n", pow((double)FULL_BLAST,(double)POWER));
-
- for ( strike = pow( (double)FULL_BLAST, (double)POWER )
- ; strike >= 1 ; strike-- ) {
- blast = FULL_BLAST / pow( (double)strike, (double)1.0/POWER );
-
- /* All the random bits together */
- r1 = random(RHO/2);
- half = random(2);
- dirn = random(2);
- r2 = ((float)rand())/(float)RAND_MAX; /* between 0 and 1 */
- x_start = random(2*RHO);
-
- /* Balance choice of riffs evenly over the surface */
- dis = sin( PI * (r1+0.5) / RHO );
- if ( r2 <= dis*dis ) rf_num = r1;
- else rf_num = RHO/2 - 1 - r1;
-
- /* We only displace the northern half, then make up for it at the end */
- if ( dirn == 0 ) blast = -blast;
- if ( half == 0 ) displac = displac - blast;
-
- /* Use riff 'rf_num' to displace an area of the surface by */
- /* depth 'blast', starting at position 'x_start' */
- /* (Warning: This function only allows RHO to be 128) */
-
- fracture(rf_num, blast, x_start);
-
- /* The 'fracture' function does something like this:
- *
- * int x1, x2, x3, x4;
- * for ( x = 0 ; x < 64 ; x++ ) {
- * x1 = ( x_start + x ) & 255;
- * x2 = ( x_start + 255 - x ) & 255;
- * for ( y = 0 ; y < riff[rf_num][x] ; y++ ) {
- * skin[y][x1] += blast;
- * skin[y][x2] += blast;
- * }
- * x3 = ( x_start + 128 + x ) & 255;
- * x4 = ( x_start + 127 - x ) & 255;
- * for ( y = 0 ; y < 127 - riff[rf_num][x] ; y++ ) {
- * skin[y][x3] += blast;
- * skin[y][x4] += blast;
- * }
- * }
- */
-
- if ( !(strike%10) ) printf(" Strike: %d \r", strike);
- }
-
-
-
- /* Find max and min heights */
- max = min = 0;
- for ( y = 0 ; y < RHO ; y++ ) {
- for ( x = 0 ; x < 2*RHO ; x++ ) {
- hgt = ( skin[y][x]+=displac );
- if ( min > hgt ) min = hgt;
- if ( max < hgt ) max = hgt;
- }
- }
- printf("Max: %d Min: %d \n", max, min);
-
- /* Rescale skin to make xion */
- printf("Rescaling\n");
- for ( y = 0 ; y < RHO ; y++ ) {
- for ( x = 0 ; x < 2*RHO ; x++ ) {
- xion[y][x] = DEEPEST + (float)(HIGHEST - DEEPEST) *
- (float)(skin[y][x] - min) / (float)(max - min);
- }
- }
-
-
-
- /* Save the complexion */
- if ( ! far_save(XION_FILE, (char far *)xion, 2*RHO*RHO) ) {
- printf("ERROR: Cannot create file %s\n", XION_FILE);
- exit(1);
- }
-
- }
-
-
-
- /* Function to save data from a 'far' array (up to 65535 bytes) */
-
- int far_save(char * fname, char far * data, unsigned len) {
- int fout;
-
- fout = f_open(fname, F_WRONLY);
- if ( fout == FILE_ERR ) return 0;
-
- f_writefar(fout, data, len);
-
- f_close(fout);
- return 1;
- }
-
-
-